/*
 * definFat32.h
 *
 *  Created on: 16/09/2011
 *      Author: Luca - Anahi
 */

#ifndef DEFINFAT32_H_
#define DEFINFAT32_H_


#include <stdint.h>
#include <stdbool.h>
#include "listas.h"


/******			Valores de entrada de FAT32		******/

#define FREE_CLUSTER			0x00000000				/* Free clusters -- also used as parent directory starting clusters
											   	   	   	   in ".." entries for subdirectories of the root directory */
#define RESERVED_VALUE			0x00000001				/* Reserved, do not use */
//#define USED_CLUSTER			0x00000002-0x0FFFFFEF 	/* Value point to the next cluster - NO SE QUE ONDA ¿¿¿??? */
//#define RESERVED_SOMETIMES	0x0FFFFFF0-0x0FFFFFF5	/* Reserved in some contexts or also used - NO SE QUE ONDA ¿¿¿??? */
#define RESERVED1_VALUE			0x0FFFFFF6				/* Reserved; do not use */
#define BAD_RESERVED_VALUE		0x0FFFFFF7				/* Bad sector in cluster or reserved cluster */
#define EOC_VALUE 			    0x0FFFFFFF	            /* Last cluster in file (End of chain) */


/******			Valores generales de la FAT32		******/

#define ENTRY_SIZE         32           /* Tamaño de la entrada de archivo o directorio */
#define SECTOR_SIZE_MAX    4096         /* La cantidad máxima de bits por sector, 512 bytes por sector */
#define SECTOR_SIZE        512
#define SECTOR_P_CLUSTER   64
#define MAX_LENGTH_NAME    13           /* Cantidad máxima de caracteres que puede tener el nombre de una entrada */
#define NAME_SIZE		   256			/* Tamaño máximo del nombre de una entrada */

/******			Valores generales de la FAT32		******/

#define DIR_ENTRY_LIBRE    0xE5         /* Entrada de directorio disponible para usar */
#define DIR_ENTRY_VACIA    0x00			/* Entrada de directorio disponible para usar y todas las siguientes entradas también */


/******			Atributos de Archivos/Directorios		******/

#define READ_ONLY				0x01
#define HIDDEN					0x02
#define SYSTEM 					0x04
#define VOLUME_LABEL			0x08
#define SUBDIRECTORY			0x10
#define ARCHIVE					0x20
#define DEVICE					0x40 		/* Internal use only, never found on disk */
#define UNUSED					0x80
#define LFN_ENTRY				READ_ONLY | HIDDEN | SYSTEM | VOLUME_LABEL



/******         Estructura - FAT32 Boot Sector       ******/

typedef struct {
	uint8_t  jumpInst[3];                   /* Jump Instruction, Offset 0x00 */
	uint8_t  OEMName[8];                    /* OEM Name, Offset 0x03 */
	uint16_t bytesPSector;                  /* Bytes per sector, Offset 0x0B */
	uint8_t  sectorsPCluster;               /* Sectors per cluster, Offset 0x0D */
	uint16_t reservedSectorCount;           /* Reserved sector count, Offset 0x0E */
	uint8_t  numberOfFATs;                  /* Number of FATs, Offset 0x10 */
	uint16_t maxRootDirectoryEntries;       /* Max number of FA2 or FAT16 root directory entries, 0 para FAT32, Offset 0x11 */
	uint16_t totalSectors;				    /* Total sectors, Offset 0x13 */
	uint8_t  mediaDescriptor;				/* Media descriptor, Offset 0x15 */
	uint16_t sectorsPFAT12y16;				/* Sectors per FAT for FAT12/FAT16, 0 para FAT32, Offset 0x16 */
	uint16_t sectorsPTrack; 				/* Sectors per track for disks, Offset 0x18 */
	uint16_t numberOfHeads;					/* Numbers of heads for disks, Offset 0x1A */
	uint32_t countHiddenSectors;			/* Count of hidden sectors, Offset 0x1C */
	uint32_t totalSectorPlus;				/* Total sectors if >65535, Offset 0x20 */

	uint32_t sectorsPerFAT;					/* Sectors per FAT, Offset 0x24 */
	uint16_t FATFlags;						/* FAT Flags, Offset 0x28 */
	uint16_t version;						/* Version de la FAT32, Offset 0x2A */
	uint32_t clustersRootDirectory;			/* Cluster number of root directory start, Offset 0x2C */
	uint16_t sectorsFSInfoSector;			/* Sector number of FS Information Sector, Offset 0x30 */
	uint16_t sectorsBackupBootSector;		/* Sector number of a copy of this boot sector, Offset 0x32 */
	uint8_t  reserved[12];					/* Reserved, Offset 0x34 */
	uint8_t  pDriveNumber;					/* Physical drive number, Offset 0x40 */
	uint8_t  reserved2;						/* Reserved, Offset 0x41 */
	uint8_t  extBootSignature;				/* Extended boot signature, Offset 0x42 */
	uint32_t ID;							/* ID (serial number), Offset 0x43 */
	uint8_t  volumeLabel[11];				/* Volume label, Offset 0x47 */
	uint8_t  FATFSType[8];					/* FAT File system type: FAT32, Offset 0x52 */
	uint8_t  OSBootCode[420];				/* Operating system boot code, Offset 0x5A */
	uint16_t bootSectorSignature;			/* Boot sector signature, Offset 0x1FE */

} __attribute__ ((packed)) t_bootsector;




/******         Estructura - FAT32 FS Information Sector       ******/

typedef struct {
	uint32_t FSInfosectorSignature;			/* FS Information sector signature, Offset 0x00 */
	uint8_t  reserved[480];					/* Reserved, Offset 0x04 */
	uint32_t FSInfosectorSignature2;		/* FS Information sector signature, Offset 0x1E4 */
	int32_t  numberFreeClusters;				/* Number of free clusters on the drive, Offset 0x1E8 */
	uint32_t mostRecentlyAllocatedCluster;	/* Number of the most recently allocated cluster, Offset 0x1EC */
	uint8_t  reserved2[12];					/* Reserved, Offset 0x1F0 */
	uint32_t FSInfoSectorSignature3;		/* FS Information sector signature, Offset 0x1FC */

} __attribute__ ((packed)) t_fsinfosector;




/******         Estructura - Entrada de directorio       ******/

typedef struct {
	char fileName[8];					/* DOS file name, Offset 0x00 */
	char  fileExtension[3];				/* DOS file extension, Offset 0x08 */
	uint8_t  fileAttributes;				/* File attributes, Offset 0x0B */
	uint8_t  reserved;						/* Reserved, Offset 0x0C */
	uint8_t  createTimefr;					/* Create time fine resolution, Offset 0x0D */
	uint16_t createTime;					/* Create time, Offset 0x0E */
	uint16_t createDate;					/* Create date, Offset 0x10 */
	uint16_t lastAccessDate;				/* Last access date, Offset 0x12 */
	uint16_t highFirstCluster;				/* High 2 bytes of first cluster number in FAT32, Offset 0x14 */
	uint16_t lastModifiedTime;				/* Last modified time, Offset 0x16 */
	uint16_t lastModifiedDate;				/* Last modified date, Offset 0x18 */
	uint16_t lowFirstCluster;				/* Low 2 bytes of first cluster in FAT32, Offset 0x1A */
	uint32_t fileSize;						/* File size in bytes, Offset 0x1C */

} __attribute__ ((packed)) t_entry;


typedef t_entry t_dir_entry;
typedef t_entry t_file_entry;



/******			Estructura - Entradas de los LFN (LONG FILE NAMES)		******/

typedef struct {
	uint8_t  sequenceNumbers;				/* Offset 0x00 */
	uint16_t nameCharacters[5];				/* Name character (five UTF-16 characters) - Offset 0x01 */
	uint8_t  attributes;					/* Always 0x0F - Offset 0x0B */
	uint8_t  reserved2;						/* Always 0x00 - Offset 0x0C */
	uint8_t  chkSumDOSfname;				/* Checksum of DOS file name - Offset 0x0D */
	uint16_t nameCharacters2[6];			/* Name characters (six UTF-16 characters) - Offset 0x0E */
	uint16_t frstCluster;					/* First Cluster (always 0x0000) - Offset 0x1A */
	uint16_t nameCharacters3[2];			/* Name characters (two UTF-16 characters) - Offset 0x1C */

} __attribute__ ((packed)) t_longFileName_entry;





/***** 			Elementos comunes a toda la FAT	(Archivos/Directorios)		******/

typedef enum {
	ENTRY_FILE 			= 0x1,
	ENTRY_DIRECTORY 	= 0x2
} tipo_entrada;

static const tipo_entrada FILE_TYPE_VALUE = ENTRY_FILE;
static const tipo_entrada DIRECTORY_TYPE_VALUE = ENTRY_DIRECTORY;


typedef struct {
	unsigned short int hours;
	unsigned short int minutes;
	unsigned short int seconds;
	unsigned short int miliseconds;
} t_time;


typedef struct {
	unsigned short int year;
	unsigned short int month;
	unsigned short int day;
} t_date;


typedef struct {
	tipo_entrada tipo;

	char	 nombreEntrada[NAME_SIZE];
	int 	 nombre_length;
	t_date   creationDate;
	t_time   creationTime;
	uint32_t firstCluster;
	uint32_t sourceClusterNumber;			/* Cluster donde persiste el elemento */
	uint32_t sourceClusterEntryNumber;		/* Numero de entrada del cluster donde el elemento persiste */

} t_element_fat;



/*****    Estructuras correspondientes a entradas de directorio y de archivo   *****/

typedef struct {
	t_element_fat  	campoFat;
	t_lista			*l_clusters; 			/* Cadena de clusters del directorio */
} t_elem_directorio;

typedef struct {
	t_element_fat  	campoFat;
	uint32_t		tamFile;
} t_elem_archivo;



/*****       Estructura de la FAT32 en general      *****/


typedef struct {

	int 			fsFileDescriptor;		/* Acá se ubica el path donde estaría montado el Fs. Es el descriptor de todo nuestro sistema */
	char*			fS;						/* Sería un puntero a la ubicacion en memoria donde se encuentra nuestro Fs */
	t_bootsector	bootSector;
	char*			baseAddrOfFSystemInfo;  /* Acá es donde empieza el FS Information Sector */
	t_fsinfosector	fileSystemInfo;
	uint32_t		*fatTable;
	uint32_t		numberOfFATEntries;
	uint32_t		tamFat;
	uint32_t		tamCluster;
	uint32_t		entradasXcluster;

} t_fat32;


#endif /* DEFINFAT32_H_ */
